package com.seari.custody.config;

import cn.hutool.core.io.FileUtil;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.RemovalCause;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import java.io.File;
import java.io.IOException;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Slf4j
@Configuration
public class CaffeineConfig {
    @Autowired
    private CacheManager cacheManager;
    public static final String COMMON = "common";
    public static final String USERS = "users_profile";
    public static final String MEETINGS = "meetings";
    public static final String PROJECTS = "projects";
    public static final String UPLOAD_FILES = "upload_files";
    public static final String MEETING_USERS = "meeting_users";

    /**
     * 定义cache名称、超时时长（秒）、最大容量
     * 每个cache缺省：10秒超时、最多缓存50000条数据，需要修改可以在构造方法的参数中指定。
     */
    enum Caches {
        COMMON_CACHE(CaffeineConfig.COMMON, Duration.ofMinutes(30).toMillis(),1000),
        //有效期2个小时 , 最大容量1000
        MEETINGS_CACHE(CaffeineConfig.MEETINGS, 7200L, 1000),
        USERS_CACHE(CaffeineConfig.USERS, 7200L, 1000),
        PROJECTS_CACHE(CaffeineConfig.PROJECTS, 7200L, 1000),
        MEETING_USERS(CaffeineConfig.MEETING_USERS, 7200L, 1000),

        UPLOAD_BIG_FILE_CHUNK_CACHE(UPLOAD_FILES, Duration.ofHours(24).toMillis(), 100000),
        ;

        Caches(String cacheName, Long ttl, Integer maxSize) {
            this.cacheName = cacheName;
            this.ttl = ttl;
            this.maxSize = maxSize;
        }

        private String cacheName;
        private Long ttl;
        private Integer maxSize;

        public String getCacheName() {
            return cacheName;
        }

        public void setCacheName(String cacheName) {
            this.cacheName = cacheName;
        }



        public int getMaxSize() {
            return maxSize;
        }

        public Long getTtl() {
            return ttl;
        }
    }

    /**
     * 创建基于Caffeine的Cache Manager
     *
     * @return
     */
    @Bean
    @Primary
    public CacheManager cacheManager() {
        SimpleCacheManager cacheManager = new SimpleCacheManager();
        ArrayList<CaffeineCache> caches = new ArrayList<>();
        for (Caches c : Caches.values()) {
            Caffeine<Object, Object> objectObjectCaffeine = Caffeine.newBuilder().recordStats()
                    .expireAfterWrite(c.getTtl(), TimeUnit.SECONDS)

                    .maximumSize(c.getMaxSize());
            if (c.getCacheName().equals(UPLOAD_FILES)) {
                objectObjectCaffeine.removalListener((String key, String value, RemovalCause cause) ->
                {
                    File file = new File(Objects.requireNonNull(value));
                    FileUtil.del(file);
                });
            }

            CaffeineCache caffeineCache = new CaffeineCache(c.getCacheName(),
                    objectObjectCaffeine.build());

            caches.add(caffeineCache
            );
        }
        cacheManager.setCaches(caches);


        return cacheManager;
    }

    @SneakyThrows
    @Bean
    public Cache fileCache() {
        Cache cache = cacheManager.getCache(UPLOAD_FILES);
        File upload = FileUtil.file(".", "upload");
        if (upload.exists()) {
            for (String fileName : Objects.requireNonNull(upload.list())) {
                if (fileName.startsWith("part")) {
                    cache.put(fileName,
                            FileUtil.file(fileName).getAbsolutePath()
                    );
                }
            }
        } else {
            upload.mkdir();
        }

        return cache;

    }

    public static void main(String[] args) {

        try {
            System.out.println(FileUtil.file(".", "upload").getCanonicalPath()
            );
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
